#include "name.h"
//根域名服务器,域名L，离北京最近
const char *ROOT = "199.7.83.42";
name::name(int off, int dns_port) {
    socketfd = socket(AF_INET,SOCK_DGRAM,0);
    localAddress.sin_port = htons(off +dns_port);
    localAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    localAddress.sin_family = AF_INET;
    bind(socketfd, (struct sockaddr *)&localAddress, sizeof(struct sockaddr));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = inet_addr(ROOT);
    serverAddress.sin_port = htons(53);
    len = sizeof(struct sockaddr);
}
// 计算ip的长度
int sum(uint8_t value) {
    int ret = 0;
    if (value < 10) {
        return 1;
    } else if (value < 100) {
        return 2;
    } else {
        return 3;
    }
}
int name::query() {
    int i = 12;
    int n = 0;
    while (buf[i++] != 0) {
        n++;
    }
    
    i = 12;
    n = 0;
    while (buf[i] != 0) {
        domain.push_back(buf[i++]);
    }
    return 0;
}
//解析每次回传的dns报文
void name::parse(uint8_t * buf) {
    int i = 9;
    int count;
    int number = buf[i++];//权威数量
    i += 2;
    while(buf[i] != 0) {
        i++;
    }
    i += 5;
    for (int n = 0; n < number; n++) {
        i += 11;
        count = buf[i] + 1;
        i += count ;
    }
    i += 12;
    i += 3;
    ip = (char *)malloc(sum(buf[i]) + sum(buf[i - 1]) + sum(buf[i - 2]) + sum(buf[i - 3]));
    sprintf(ip, "%d.%d.%d.%d", buf[i--], buf[i--], buf[i--], buf[i--]);
}
nums parse_answer (uint8_t *buf, int &count) {
    nums ret;
    for (int i = 0; i < count; i++) {
        ret.push_back(buf[i]);
    }
    return ret;
}
void answer_buf (uint8_t *buf, nums &answer) {
    for (int i = 0; i < answer.size(); i++) {
        buf[i] = answer[i];
    }
}
void name::process() {
    //发送给root服务器
    query();
    nums ret = lru->select(domain);
    if (ret.size() == 0) {
    }
    else {
        answer_buf(sendbuf, ret);
        sendbuf[0] = buf[0];sendbuf[1] = buf[1];
        sendto(mainSocketfd, sendbuf, sizeof(sendbuf), 0, (struct  sockaddr*)&clientAddress, len); 
        return ;
    }
    r_ptr->pass();
    sendto(socketfd, buf, count, 0, (struct  sockaddr*)&serverAddress, len);
    memset(buf, sizeof(buf), 0);
    int c = recvfrom(socketfd, sendbuf, sizeof(buf), 0, (struct sockaddr *)&serverAddress, &len);
    parse(sendbuf);
    serverAddress.sin_addr.s_addr = inet_addr(ip);
    //发送给顶级服务器
    r_ptr->pass();
    sendto(socketfd, buf, count, 0, (struct  sockaddr*)&serverAddress, len);
    memset(sendbuf,sizeof(sendbuf),0);
    c = recvfrom(socketfd, sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&serverAddress, &len);
    parse(sendbuf);
    serverAddress.sin_addr.s_addr = inet_addr(ip);
    //发送给权威服务器
    r_ptr->pass();
    sendto(socketfd, buf, count, 0, (struct  sockaddr*)&serverAddress, len);
    memset(sendbuf,sizeof(sendbuf),0);
    c = recvfrom(socketfd, sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&serverAddress, &len);
    //发送给请求者
    r_ptr->pass();
    sendto(mainSocketfd, sendbuf, sizeof(sendbuf), 0, (struct  sockaddr*)&clientAddress, len); 
    nums value = parse_answer(sendbuf , c);
    if ( value.size() != 0) {
        lru->put(domain,value);
    }

}